#!/bin/bash
#
# Copyright 2015-2017 Adrian DC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# === Shell Entrypoint Handling ===
ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT=${BASH_SOURCE[0]};
ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT=${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT:-${(%):-%N}};
if [ -z "${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}" ]; then
  echo '';
  echo -e ' \e[1;33mandroid_development_shell_tools by AdrianDC: \e[0;33mExecution path could not be found\e[0m';
  echo '';
  return;
fi;

# === Android Development Shell Tools Folder ===
ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH=${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH:-master};
ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR=$(dirname "${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}");
ANDROID_DEVELOPMENT_SHELL_TOOLS_EXTENSIONS=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/extensions;
ANDROID_DEVELOPMENT_SHELL_TOOLS_SCRIPTS=();
ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES=();

# === Android Development Shell Tools Variables ===
ANDROID_DEVELOPMENT_SHELL_TOOLS_URL='https://github.com/AdrianDC/android_development_shell_tools';

# === Android Development Shell Tools Workspace ===
if [ -z "${ANDROID_DEVELOPMENT_SHELL_TOOLS_WORKSPACE:-${HOME}}" ]; then
  export ANDROID_DEVELOPMENT_SHELL_TOOLS_WORKSPACE=~;
fi;

# === Android Development Shell Tools Update ===
function shtoolsup()
{
  # Usage: shtoolsup (Reloads android_development_shell_tools scripts)

  # Reload sources
  source "${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}";
  echo '';
  echo -e ' \e[1;33mandroid_development_shell_tools by AdrianDC: \e[0;33mFunctions loaded properly\e[0m';
  echo '';
}

# === Android Development Shell Tools Sources ===
function __shtoolssources()
{
  # Variables
  local LC_ALL_HOST;

  # Locale override
  LC_ALL_HOST=${LC_ALL};
  export LC_ALL=C;

  # Android Development Shell Tools Sources
  ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES=();
  for path in "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/"*'.rc'; do
    if [ ! "${path}" = "${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}" ]; then
      ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES+=("${path}");
    fi;
  done;
  for path in "${ANDROID_DEVELOPMENT_SHELL_TOOLS_EXTENSIONS}/"*'/'*'.rc'; do
    ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES+=("${path}");
  done;

  # Android Development Shell Tools Scripts
  ANDROID_DEVELOPMENT_SHELL_TOOLS_SCRIPTS=();
  for path in "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/"*'.sh'; do
    ANDROID_DEVELOPMENT_SHELL_TOOLS_SCRIPTS+=("${path}");
  done;

  # Android Development Shell Tools Inclusion
  for file_source in "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES[@]}"; do
    source "${file_source}";
  done;

  # Locale restore
  export LC_ALL=${LC_ALL_HOST};
}

# === Android Development Shell Tools Sources Inclusion ===
__shtoolssources;

# === Android Development Shell Tools Prebuilt Files ===
export ANDROID_DEVELOPMENT_SHELL_TOOLS_FILES_STRACE_32=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/android_binaries/strace_arm32;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_FILES_STRACE_64=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/android_binaries/strace_arm64;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_FILES_TINYMIX=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/android_binaries/tinymix;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_FLASHABLE_ANDROID_BASE=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/flashable_android_base.zip;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_SCRIPTS_KERNEL_INJECTOR=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/kernel_inject;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_SCRIPTS_KERNEL_INJECTOR_SH=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/kernel_inject.sh;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_SIGNAPK_DIR=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/signapk;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_UPDATER_FLASH_BOOT=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/updater_script_flash_boot;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_UPDATER_FLASH_FOTA=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/updater_script_flash_fota;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_UPDATER_INSTALL_OEM=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/updater_script_install_oem;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_UPDATER_INSTALL_SYSTEM=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/updater_script_install_system;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_UPDATER_KERNEL_INJECTOR=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/updater_script_kernel_injector;
export ANDROID_DEVELOPMENT_SHELL_TOOLS_UPDATER_MULTIROM_SECONDARY=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/addons/flashables/updater_script_multirom_secondary;

# === Android Development Shell Tools Path Getter ===
function shtoolsget()
{
  # Usage: shtoolsget (Get android_development_shell_tools path)

  # Get android_development_shell_tools path
  echo "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}";
}

# === Android Development Shell Tools Path Access ===
function shtoolscd()
{
  # Usage: shtoolscd (Access android_development_shell_tools path)

  # Access android_development_shell_tools path
  cd "$(shtoolsget)";
}

# === Android Development Shell Tools Functions Editor ===
function shtoolse()
{
  # Usage: shtoolse <words> <to> <search> (Direct access to related sources)

  # Variables
  local files=();

  # Study all script files
  for file_source in "${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}" "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES[@]}"; do
    for word in "${@}"; do

      # List found files
      if grep -aiq "${word}" "${file_source}"; then
        files+=("${file_source}");
        continue;
      fi;
    done;
  done;

  # Open listed files
  if [ ! -z "${files[*]}" ]; then
    fileedit "${files[@]}";
  fi;
}

# === Android Development Shell Tools Functions Editor ===
function shtoolsf()
{
  # Usage: shtoolsf <function_or_alias> (Direct access to related function or alias sources)

  # Launch shtoolse with function or alias syntax
  shtoolse "${1}()" "${1}=";
}

# === Android Development Shell Tools Syntax Checker ===
function shtoolscheck()
{
  # Usage: shtoolscheck [bool_ignore] (Run ShellCheck on the project)

  # Variables
  local file_source;

  # Study all script files
  echo -e '\e[1;37m';
  for file_source in "${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}" "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES[@]}" "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SCRIPTS[@]}"; do

    # Parsing header
    echo -en "\r\033[K shtoolscheck: Checking ${file_source}...";

    # Launch ShellCheck
    if ! shellcheck "${file_source}" \
        -e SC1090,SC1091,SC2164 \
        && [ -z "${1}" ]; then
      echo -e " \e[1;33mERROR: ${file_source} contains syntax errors or warnings\e[0m";
      echo '';
      return;
    fi;
  done;

  # Successfull syntax check
  echo -e '\r\033[K \e[1;32mshtoolscheck: Syntax checked successfully\e[0m';
  echo '';
}

# === Android Development Shell Tools Syncer ===
function shtoolssync()
{
  # Usage: shtoolssync (Download new android_development_shell_tools changes)

  # Download upstream changes
  local currentdir=${PWD};
  cd "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/";
  git fetch origin;
  git reset "origin/${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}";
  git stash -u;
  git submodule init;
  git submodule update;
  cd "${currentdir}/";
  shtoolsup;
}

# === Android Development Shell Tools Pusher ===
function shtoolspush()
{
  # Usage: shtoolspush [bool_ignore_readme] (Commit new changes to android_development_shell_tools)

  # Update README.md
  if [ -z "${1}" ]; then
    shtoolsreadme;
  fi;

  # Commit changes
  local currentdir=${PWD};
  cd "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/";
  git add -N ./*;
  git add . -Ap;
  git commit -s;

  # Commits stats with upstream
  git fetch origin "${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}";
  echo '';
  echo -n ' New changes - missing : ';
  git rev-list --left-right --count HEAD...FETCH_HEAD;
  echo '';

  # Push to upstream
  git push -f origin "HEAD:${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}";
  cd "${currentdir}/";
  shtoolsup;
}

# === Android Development Shell Tools Amend ===
function shtoolsamend()
{
  # Usage: shtoolsamend [bool_ignore_readme] [bool_ignore_message] (Amend new changes to android_development_shell_tools)

  # Update README.md
  if [ -z "${1}" ]; then
    shtoolsreadme;
  fi;

  # Commit changes
  local currentdir=${PWD};
  cd "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/";
  git add -N ./*;
  git add . -Ap;
  if [ -z "${2}" ]; then
    git commit -s --amend;
  else
    git commit -s --amend --no-edit;
  fi;

  # Commits stats with upstream
  git fetch origin "${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}";
  echo '';
  echo -n ' New changes - missing : ';
  git rev-list --left-right --count HEAD...FETCH_HEAD;
  echo '';

  # Push to upstream
  git push -f origin "HEAD:${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}";
  cd "${currentdir}/";
  shtoolsup;
}

# === Android Development Shell Tools Menu ===
function shtools()
{
  # Usage: shtools (Entrypoint menu to android_development_shell_tools)

  # Variables
  local cnt=0;
  local key;
  local line_function;
  local line_usage;
  local list_functions=('');

  # Function header
  echo '';
  echo -e " \e[1;37m[ Android Development Shell Tools - Menu ]\e[0m";
  echo '';

  # Display shtools* menu
  for line_function in $(typeset -F | grep shtools | cut -d' ' -f 3 | grep -v '^shtools$'); do

    # Parse usage
    line_usage=$(grep -a "Usage: ${line_function} " "${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}");
    if [ -z "${line_usage}" ]; then
      continue;
    fi;
    line_usage=${line_usage#*\(};
    line_usage=${line_usage%\)*};
    list_functions+=("${line_function}");

    # Item choice
    cnt=$((cnt + 1));
    echo -e "  \e[1;33m${cnt}: \e[1;37m${line_function} \e[1;32m[${line_usage}]\e[0m";

  done;
  echo '';

  # Request user input
  echo -n " > Command to run [1-${cnt}] : ";
  read -r key;
  echo '';

  # Execute requested function
  ${list_functions[${key}]};
}

# === Android Development Shell Tools Options Menu ===
function shtools-()
{
  # Usage: shtools- (Options menu for android_development_shell_tools)

  # Variables
  local active;
  local cnt;
  local key;
  local line_function;
  local line_option;
  local line_usage;
  local list_functions;

  # Loop until user exits
  key=-1;
  echo '';
  while [ ! "${key}" = '0' ] && [ ! "${key}" = 'q' ]; do

    # Function header
    echo '';
    echo -e " \e[1;37m[ Android Development Shell Tools - Options ]\e[0m";
    echo '';

    # Reset containers
    active=0;
    cnt=0;
    list_functions=('');

    # Display shtools-* active options
    for line_function in $(typeset -F | grep 'shtools-' | cut -d' ' -f 3 \
                         | grep -v '^shtools-$' \
                         | grep '\-enable$'); do

      # Verify if the option is active
      cnt=$((cnt + 1));
      line_option=${line_function%-enable};
      line_option=${line_option#shtools-};
      if [ ! "${line_option}" = "${line_function}" ] && "shtools-${line_option}-active" 2> /dev/null; then

        # Parse usage
        line_usage=$(grep -a "Usage: ${line_function} " "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES[@]}");
        if [ -z "${line_usage}" ]; then
          continue;
        fi;
        line_usage=${line_usage#*\(};
        line_usage=${line_usage%\)*};

        # Present active option
        active=$((active + 1));
        echo -e "  \e[1;33mOption ${cnt} active: \e[1;37m${line_option} \e[1;32m[${line_usage}]\e[0m";

      fi;
    done;

    # Detected active options
    if [ "${active}" -ne 0 ]; then
      echo '';
    fi;
    cnt=0;

    # Display exit item
    echo -e "  \e[1;33m0: \e[1;37mKeep current options \e[1;32m[Exit the configuration]\e[0m";

    # Display shtools-* menu
    for line_function in $(typeset -F | grep 'shtools-' | cut -d' ' -f 3 \
                         | grep -v '^shtools-$' \
                         | grep -v '\-active$'); do

      # Verify if the option is active
      line_option=${line_function%-enable};
      if [ ! "${line_option}" = "${line_function}" ] && "${line_option}-active" 2> /dev/null; then
        continue;
      fi;

      # Verify if the option is inactive
      line_option=${line_function%-disable};
      if [ ! "${line_option}" = "${line_function}" ] && ! "${line_option}-active" 2> /dev/null; then
        continue;
      fi;

      # Parse usage
      line_usage=$(grep -a "Usage: ${line_function} " "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES[@]}");
      if [ -z "${line_usage}" ]; then
        continue;
      fi;
      line_usage=${line_usage#*\(};
      line_usage=${line_usage%\)*};
      list_functions+=("${line_function}");

      # Item choice
      cnt=$((cnt + 1));
      echo -e "  \e[1;33m${cnt}: \e[1;37m${line_function} \e[1;32m[${line_usage}]\e[0m";

    done;
    echo '';

    # Request user input
    echo -n " > Command to run [0-${cnt}] : ";
    read -r key;
    echo '';

    # Execute requested function
    if [ "${key}" -eq "${key}" ] 2> /dev/null && [ "${key}" -ge 1 ] && [ "${key}" -le "${cnt}" ]; then
      ${list_functions[${key}]};
    fi;

  done;
}

# === Android Development Shell Tools Options ===
function __shtoolsoptions()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: __shtoolsoptions <option_prefix> [option_set] (Settings holder for android_development_shell_tools)';
    echo '';
    return;
  fi;

  # Filter iterative calls
  if [ ! -z "${ANDROID_DEVELOPMENT_SHELL_TOOLS_OPTIONS_LOAD}" ]; then
    return;
  fi;

  # Variables
  local option_command;
  local options_file=${ANDROID_DEVELOPMENT_SHELL_TOOLS_WORKSPACE:-${HOME}}/.bash_android_development_shell_tools.rc;

  # Store given input option
  if [ ! -z "${2}" ]; then

    # Create initial empty configuration
    if [ ! -f "${options_file}" ]; then
      { echo '#!/bin/bash';
        echo '#';
        echo '# Android Development Shell Tools - Options';
        echo '#'; } > "${options_file}";
    fi;

    # Update existing option
    if grep -q "${1}" "${options_file}"; then
      sed -i "s/${1}.*/${1}${2}/" "${options_file}";

    # Define new option
    else
      echo "${1}${2}" >> "${options_file}";
    fi;

  # Acquire current options
  else
    if [ -f "${options_file}" ]; then
      option_command=$(grep "${1}" "${options_file}");
      if [ ! -z "${option_command}" ]; then
        export ANDROID_DEVELOPMENT_SHELL_TOOLS_OPTIONS_LOAD=true;
        ${option_command};
        export ANDROID_DEVELOPMENT_SHELL_TOOLS_OPTIONS_LOAD=;
      fi;
    fi;
  fi;
}

# === Android Development Shell Tools Stats ===
function shtoolsstats()
{
  # Usage: shtoolsstats (Statistics on the project files)

  # Variables
  local currentdir=${PWD};
  local paths;

  # List all project files
  paths=("${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}" "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES[@]}" "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SCRIPTS[@]}");
  paths=("${paths[@]#${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/}");

  # Statistics on the project files
  echo '';
  echo ' Lines| Sizes| Paths';
  cd "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/";
  wc -cl "${paths[@]}";
  echo '';
  cd "${currentdir}/";
}

# === Android Development Shell Tools Differ ===
function shtoolsdiff()
{
  # Usage: shtoolsdiff (Compare with upstream android_development_shell_tools)

  # Compare with upstream
  local currentdir=${PWD};
  cd "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/";
  git fetch origin;
  git diff HEAD "origin/${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}";
  git diff HEAD;
  cd "${currentdir}/";
}

# === Android Development Shell Tools Log ===
function shtoolslog()
{
  # Usage: shtoolslog (Display android_development_shell_tools history)

  # Display project history
  local currentdir=${PWD};
  cd "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/";
  git log --pretty=oneline -n 10;
  cd "${currentdir}/";
}

# === Android Development Shell Tools Reset ===
function shtoolsreset()
{
  # Usage: shtoolsreset (Reset project to remote HEAD)

  # Reset project to remote HEAD
  cd "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/";
  git fetch origin;
  git reset "origin/${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}";
  git diff --stat HEAD;
}

# === Android Development Shell Tools Master ===
function shtoolsmaster()
{
  # Usage: shtoolsmaster (Switch android_development_shell_tools to master branch)

  # Switch android_development_shell_tools to master branch
  local branch=${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH};
  ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH=master;
  echo '';
  echo -e " \e[1;33mandroid_development_shell_tools: \e[0;33mSwitched from '${branch}' to '${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}' branch\e[0m";
  echo '';
}

# === Android Development Shell Tools Staging ===
function shtoolsstaging()
{
  # Usage: shtoolsstaging (Switch android_development_shell_tools to staging branch)

  # Switch android_development_shell_tools to staging branch
  local branch=${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH};
  ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH=staging;
  echo '';
  echo -e " \e[1;33mandroid_development_shell_tools: \e[0;33mSwitched from '${branch}' to '${ANDROID_DEVELOPMENT_SHELL_TOOLS_BRANCH}' branch\e[0m";
  echo '';
}

# === Android Development Shell Tools README.forum Updater ===
function shtoolsforum()
{
  # Usage: shtoolsforum (Refresh README.forum project presentation)

  # Variables
  local preview_file;
  local preview_files;
  local preview_timestamp;
  local readme_forum=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/forums/README;
  local readme_md=${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/README;

  # Header
  echo '';
  echo -e ' \e[1;33mandroid_development_shell_tools:\e[0;33m Building README forum documentations\e[0m';
  echo '';

  # Handle multiple README files
  for ext in md previews.md samples.md; do

    # Prepare README.forum
    rm -f "${readme_forum}.${ext}";
    cp -v "${readme_md}.${ext}" "${readme_forum}.${ext}";

    # Convert from markdown to bbcode
    sed -i 's#!\[.*\](\(.*\))#[IMG]\1[/IMG]#g' "${readme_forum}.${ext}";
    sed -i 's#\[\([^]]*\)\](\([^)]*\))#[URL=\2]\1[/URL]#g' "${readme_forum}.${ext}";
    sed -i '/^[ ]*<br \/>$/d' "${readme_forum}.${ext}";
    sed -i "s#\`\`\`\(cpp\|Shell\)#[CODE]#g" "${readme_forum}.${ext}";
    sed -i "s#\`\`\`#[/CODE]#g" "${readme_forum}.${ext}";
    sed -i "s#\(\`.*\`\)#[FONT=\"Courier New\"][I]\1[/I][/FONT]#g" "${readme_forum}.${ext}";
    sed -i 's#^\#\#\# \(.*\)$#[SIZE=5][B]\1[/B][/SIZE]#g' "${readme_forum}.${ext}";
    sed -i 's#^\#\#\#\# \(.*\)$#[SIZE=4][B]\1[/B][/SIZE]#g' "${readme_forum}.${ext}";
    sed -i ':a;N;$!ba;s#<!-- Center -->\n#[CENTER]#g;s#\n<!-- /Center -->#[/CENTER]#g' "${readme_forum}.${ext}";
    sed -i ':a;N;$!ba;s#<!-- Indent -->\n#[INDENT]#g;s#\n<!-- /Indent -->#[/INDENT]#g' "${readme_forum}.${ext}";
    sed -i 's#<!-- \(\|/\)List -->#[\1LIST]#g' "${readme_forum}.${ext}";
    sed -i 's#^ \* #[*]#g' "${readme_forum}.${ext}";
    sed -i 's#\*\*\([^*]*\)\*\*#[B]\1[/B]#g' "${readme_forum}.${ext}";
    sed -i 's#\*\([^]]\{1\}[^*]*\)\*#[I]\1[/I]#g' "${readme_forum}.${ext}";
    sed -i 's#__\([^*]*\)__#[U]\1[/U]#g' "${readme_forum}.${ext}";

    # Get all previews png files
    preview_files=$(grep 'docs/assets.*\.png' "${readme_forum}.${ext}" \
                  | sed "s/.*${ANDROID_DEVELOPMENT_SHELL_TOOLS_URL//\//\\\/}\/raw\/master\/\(.*\.png\).*/\1/g");
    for preview_file in ${preview_files}; do

      # Filter out wrong outputs
      if [ ! -f "${preview_file}" ]; then
        continue;
      fi;

      # Get file timestamp and replace text
      preview_timestamp=$(stat -c %Y "${preview_file}");
      sed -i "s#${preview_file}#${preview_file}?timestamp=${preview_timestamp}#g" "${readme_forum}.${ext}";
    done;

  done;

  # Parsed header
  echo '';
  echo '  README forum files successfully rebuilt';
  echo '';
}

# === Android Development Shell Tools README.md Updater ===
function shtoolsreadme()
{
  # Usage: shtoolsreadme (Refresh README.md functions usages)

  # Variables
  local command_file;
  local delimiter_start='<!-- Functions Start -->';
  local delimiter_end='<!-- Functions End -->';
  local github_project_url=${ANDROID_DEVELOPMENT_SHELL_TOOLS_URL//\//\\\/};
  local github_file_path='blob\/master';
  local github_raw_path='raw\/master';
  local line;
  local line_function;
  local line_standalone;
  local line_summary;
  local line_type;
  local line_usage;
  local path;
  local readme_functions=;
  local stats_aliases=0;
  local stats_functions=0;
  local stats_sources=0;

  # Initialize variables
  command_file=$(mktemp);

  # Unify locale for sorting
  local lc_all=${LC_ALL};
  LC_ALL=C;

  # Refresh files list
  shtoolsup;

  # Header
  echo -e ' \e[1;33mandroid_development_shell_tools:\e[0;33m Building README.md documentation\e[0m';
  echo -n '  ...';

  # Refresh project's README.md
  cp -f "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/README.md" "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/docs/project.md";

  # Read all sources
  for file in "${ANDROID_DEVELOPMENT_SHELL_TOOLS_ENTRYPOINT}" \
              "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SOURCES[@]}" \
              "${ANDROID_DEVELOPMENT_SHELL_TOOLS_SCRIPTS[@]}"; do

    # Handle file path
    path=${file##${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/};
    stats_sources=$((stats_sources + 1));

    # Parsing header
    echo -en "\r\033[K  Parsing ${path}";

    # Escape path
    path=${path//\//\\\/};

    # Detect standalone ready scripts
    line_standalone=$(grep -a '^# source <(curl -Ls' "${file}");

    # Detect .sh executable scripts
    if [ "${path: -3}" = '.sh' ]; then
      line_standalone=${github_project_url//\\\//\/}/${github_raw_path//\\\//\/}/${path};
    fi;

    # Create source section
    readme_functions+="### \[\&nbsp;Documentation: [${path}](${github_project_url}\/${github_file_path}\/${path})\&nbsp;\]\n";

    # Inject standalone import script
    if [ ! -z "${line_standalone}" ]; then
      line_standalone=${line_standalone//# source <\(curl -Ls/};
      line_standalone=${line_standalone//)/};
      readme_functions+="  \`\`\`Shell\n";
      for url in ${line_standalone}; do
        readme_functions+="source \<\(curl -Ls ${url//\//\\\/}\)\n";
      done;
      readme_functions+="  \`\`\`\n";
    fi;

    # Handle shell scripts content
    if [ "${path: -3}" = '.sh' ]; then

      # Parse shell script usage
      line_function=${path#*\/};
      line_function=${line_function%.sh};
      line_usage=$(grep -a "Usage: ${line_function}" "${file}");

      # Warning about missing usages
      if [ -z "${line_usage}" ]; then
        echo '';
        echo " ${path}: ERROR: '${line_function}.sh' has no usage";
        echo '';
       return;
      fi;

      # Parse usage and summary details
      line_summary=${line_usage#*\(};
      line_summary=${line_summary%\)*};
      line_usage=${line_usage/ \(*\)/};
      line_usage=${line_usage#\# Usage: };

      # Apply summary styling
      line_summary="<b>\\\[${line_summary}\\\]<\\/b>";

      # Append function details
      readme_functions+="  * [**\\\.\/${line_usage}** *${line_summary}*](${github_project_url}\/${github_file_path}\/${path//./\\\.})\n";

      # Sections separation
      readme_functions+="\n---\n";

      # Continue with the next file
      continue;

    fi;

    # Handle source contents
    # shellcheck disable=SC2162
    while read line; do

      # Parse source functions
      line_function=${line};
      line_function=${line_function#function };
      line_function=${line_function#alias };
      line_function=${line_function%%()*};
      line_function=${line_function%%=*};
      line_type=${line};
      line_type=${line_type//*alias*/Alias};
      line_type=${line_type//*function*/Function};
      line_summary="\(${line_type}\)";
      line_usage=;

      # Hide internal functions starting by __
      if [ "${line_function:0:2}" = '__' ]; then
        continue;
      fi;

      # Parse function content
      if [ "${line_type}" = 'Function' ]; then

        # Parse single line function
        if [[ "${line}" == *"${line_function}()"*"{"*"}" ]]; then
          line_usage=${line#*\{ };
          line_usage=${line_usage% \}*};
          line_usage=${line_usage%;};
          line_usage=${line_usage// 2>*\/dev\/null/};
          stats_functions=$((stats_functions + 1));

        # Parse function usage
        else
          line_usage=$(grep -a "Usage: ${line_function}\( \|'\|\"\)" "${file}");
          line_usage=${line_usage#*Usage: };
          line_usage=${line_usage%;};
          line_usage=${line_usage%$"'"};
          line_usage=${line_usage%$'"'};
          stats_functions=$((stats_functions + 1));

          # Mark function summary field
          if [[ "${line_usage}" == *"("*")"* ]]; then
            line_usage=${line_usage/ \(/-SUMMARY-};
            line_usage=${line_usage/\)*/-SUMMARY-};

          # Warning about missing description
          else
            echo " ${path}: ${line_type} '${line_function}' has no description";
          fi;
        fi;

      # Parse alias content
      elif [ "${line_type}" = 'Alias' ]; then
        line_usage=${line};
        line_usage=${line_usage#*=};
        line_usage=${line_usage%;};
        line_usage=${line_usage#$"'"};
        line_usage=${line_usage#$'"'};
        line_usage=${line_usage%$"'"};
        line_usage=${line_usage%$'"'};
        stats_aliases=$((stats_aliases + 1));
      fi;

      # Apply usage formattings
      if [ ! -z "${line_usage}" ]; then
        line_usage=${line_usage//\</&lt;};
        line_usage=${line_usage//\>/&gt;};
        line_usage=${line_usage//\//\\\/};
        line_usage=${line_usage//\|/\\\\\|};
        line_usage=${line_usage//\&/\\\&};
        line_usage=${line_usage//$"'"/\\$"'"};
        line_usage=${line_usage//$'"'/\\$'"'};
        line_usage=${line_usage//\$/\\\$};
        line_usage=${line_usage% };

        # Parse summary out
        if [[ "${line_usage}" == *"-SUMMARY-"*"-SUMMARY-"* ]]; then
          line_summary=${line_usage#*-SUMMARY-};
          line_summary=${line_summary%-SUMMARY-*};
          line_usage=${line_usage/-SUMMARY-*-SUMMARY-/};

          # Apply summary styling
          line_summary="<b>\\\[${line_summary}\\\]<\/b>";
        fi;

        # Apply usage styling
        if [ ! "${line_usage}" = "${line_function}" ]; then
          line_usage=" : *${line_usage}*";

        # Ignore function usage
        else
          line_usage=;
        fi;

      # Warning about missing usages
      else
        echo '';
        echo " ${path}: ERROR: ${line_type} '${line_function}' has no usage";
        echo '';
        return;
      fi;

      # Append function details
      readme_functions+="  * [**${line_function}** *${line_summary}*](${github_project_url}\/${github_file_path}\/${path})${line_usage}\n";

    done < <(grep -a "^alias.*=\|^function .*()" "${file}");

    # Sections separation
    readme_functions+="\n---\n";

  done;

  # Generation information
  readme_functions+="* #### Automatically generated by [shtoolsreadme](${github_project_url}\/${github_file_path}\/android_development_shell_tools.rc) for [android_development_shell_tools](${github_project_url})\n";

  # Inject README.md changes
  # shellcheck disable=SC2028
  echo "/${delimiter_start}/{p; :a; N; /${delimiter_end}/!ba; s/.*\n/${readme_functions}/; };" > "${command_file}";
  sed -i -f "${command_file}" "${ANDROID_DEVELOPMENT_SHELL_TOOLS_DIR}/docs/README.md";
  rm "${command_file}";

  # Restore locale
  LC_ALL=${lc_all};

  # Parsed header
  echo -e "\r\033[K  \e[1;37mREADME.md successfully rebuilt:\e[0m ${stats_functions} functions and ${stats_aliases} aliases in ${stats_sources} sources";
  echo '';
}
